"""
pygame可视化模块
实时显示游戏地图、单位位置、探测范围等

作者：wjttdbx
版本：1.0
"""
import pygame
import math
import sys
import os
import time
from typing import List, Optional, Dict, Tuple
from core.units import WhiteBoat, WhiteDrone, BlackBoat
from core.utils import POLYGON_POINTS, DEPLOYMENT_LINE_START, DEPLOYMENT_LINE_END, BREAKTHROUGH_LINE_START, BREAKTHROUGH_LINE_END
from core.config import GameConfig

# 初始化pygame
pygame.init()

# 设置中文字体支持
def get_chinese_font(size=16):
    """获取支持中文的字体"""
    font_paths = [
        "NotoSansSC-Regular.ttf"
    ]
    
    for font_path in font_paths:
        if os.path.exists(font_path):
            try:
                return pygame.font.Font(font_path, size)
            except:
                continue
    
    # 如果找不到中文字体，使用默认字体
    return pygame.font.Font(None, size)


class InfoPanelData:
    """信息面板数据收集器"""
    
    def __init__(self):
        self.last_known_positions = {}  # 记录黑方最后已知位置
        self.lost_targets = {}  # 失联目标信息
        self.threat_history = {}  # 威胁历史记录
        self.last_update_time = time.time()
        
    def collect_white_boat_info(self, boats: List[WhiteBoat], current_time: float) -> List[Dict]:
        """收集白方无人船信息"""
        boat_info = []
        for boat in boats:
            if not boat.active:
                continue
                
            status = self._get_boat_status(boat, current_time)
            target_info = self._get_boat_target_info(boat)
            
            info = {
                'id': boat.id,
                'position': (int(boat.x), int(boat.y)),
                'status': status,
                'target': target_info,
                'speed': boat.speed,
                'heading': math.degrees(boat.heading),
                'locked_target': boat.current_target.id if boat.current_target else None,
                'lock_progress': self._get_lock_progress(boat, current_time) if boat.is_locking else 0
            }
            boat_info.append(info)
        return boat_info
    
    def collect_drone_info(self, drones: List[WhiteDrone]) -> List[Dict]:
        """收集白方无人机信息"""
        drone_info = []
        for drone in drones:
            # 包括所有状态的无人机：flying, recharging
            info = {
                'id': drone.id,
                'position': (int(drone.x), int(drone.y)),
                'energy': drone.energy,
                'mode': self._get_drone_mode(drone),
                'parent_boat': drone.parent_boat_id,
                'speed': drone.speed,
                'heading': math.degrees(drone.heading),
                'state': drone.state
            }
            drone_info.append(info)
        return drone_info
    
    def analyze_threats(self, black_boats: List[BlackBoat], white_boats: List[WhiteBoat], 
                       white_drones: List[WhiteDrone], current_time: float) -> Tuple[List[Dict], List[Dict]]:
        """分析威胁目标，返回确认目标和预测目标"""
        detected_targets = []
        predicted_targets = []
        
        # 获取当前探测到的黑方目标
        detected_ids = set()
        for black_boat in black_boats:
            if not black_boat.active:
                continue
                
            is_detected = self._is_target_detected(black_boat, white_boats, white_drones)
            if is_detected:
                detected_ids.add(black_boat.id)
                threat_level = self._calculate_threat_level(black_boat)
                distance_to_breakthrough = self._calculate_distance_to_breakthrough(black_boat)
                eta = self._calculate_eta_to_breakthrough(black_boat)
                detected_by = self._get_detected_by(black_boat, white_boats, white_drones)
                
                threat_info = {
                    'id': black_boat.id,
                    'position': (int(black_boat.x), int(black_boat.y)),
                    'threat_level': threat_level,
                    'distance_to_breakthrough': distance_to_breakthrough,
                    'eta_minutes': eta,
                    'speed': black_boat.speed,
                    'heading': math.degrees(black_boat.heading),
                    'detected_by': detected_by
                }
                detected_targets.append(threat_info)
                
                # 更新最后已知位置
                self.last_known_positions[black_boat.id] = {
                    'position': (black_boat.x, black_boat.y),
                    'heading': black_boat.heading,
                    'speed': black_boat.speed,
                    'time': current_time
                }
        
        # 处理失联目标
        for boat_id, last_known in self.last_known_positions.items():
            if boat_id not in detected_ids:
                # 检查对应的黑方艇是否仍然活跃
                boat_still_active = False
                for black_boat in black_boats:
                    if black_boat.id == boat_id and black_boat.active:
                        boat_still_active = True
                        break
                
                # 如果黑方艇已经不活跃，跳过预测
                if not boat_still_active:
                    continue
                
                lost_time = current_time - last_known['time']
                if lost_time > 5.0:  # 失联超过5秒才显示预测
                    predicted_pos = self._predict_position(last_known, lost_time)
                    confidence = max(0.1, 1.0 - lost_time / 300.0)  # 5分钟后置信度降到最低
                    
                    predicted_info = {
                        'id': boat_id,
                        'last_known_position': (int(last_known['position'][0]), int(last_known['position'][1])),
                        'predicted_position': (int(predicted_pos[0]), int(predicted_pos[1])),
                        'lost_time': lost_time,
                        'confidence': confidence
                    }
                    predicted_targets.append(predicted_info)
        
        # 按威胁等级排序确认目标
        detected_targets.sort(key=lambda x: (-x['threat_level'], x['distance_to_breakthrough']))
        
        return detected_targets, predicted_targets
    
    def _get_boat_status(self, boat: WhiteBoat, current_time: float) -> str:
        """获取无人船状态"""
        if boat.is_frozen(current_time):
            return "冻结"
        elif boat.is_locking and boat.current_target:
            return "锁定"
        elif boat.current_target:
            return "拦截"
        else:
            return "巡逻"
    
    def _get_boat_target_info(self, boat: WhiteBoat) -> Optional[Tuple[int, int]]:
        """获取无人船目标信息"""
        if boat.current_target:
            return (int(boat.current_target.x), int(boat.current_target.y))
        return None
    
    def _get_lock_progress(self, boat: WhiteBoat, current_time: float) -> float:
        """获取锁定进度"""
        if not boat.is_locking:
            return 0.0
        lock_duration = boat.get_lock_duration(current_time)
        return min(1.0, lock_duration / GameConfig.WHITE_BOAT_LOCK_DURATION)
    
    def _get_drone_mode(self, drone: WhiteDrone) -> str:
        """获取无人机模式"""
        if drone.state == "ready":
            return "待机"
        elif drone.state == "recharging":
            return "充电"
        elif drone.state == "flying":
            # 用mode属性区分
            mode = getattr(drone, 'mode', None)
            if mode == 1:
                return "跟踪"
            elif mode == 0:
                return "返回"
            elif mode is not None:
                return "巡逻"
            return "飞行"
        return "未知"
    
    def _is_target_detected(self, black_boat: BlackBoat, white_boats: List[WhiteBoat], 
                           white_drones: List[WhiteDrone]) -> bool:
        """判断目标是否被探测到"""
        # 检查无人船探测
        for white_boat in white_boats:
            if not white_boat.active:
                continue
            distance = white_boat.distance_to(black_boat)
            if distance <= GameConfig.WHITE_BOAT_DETECT_RANGE:
                return True
        
        # 检查无人机探测
        for drone in white_drones:
            if drone.state != "flying":
                continue
            if drone.is_target_in_detection_sector(black_boat, drone.heading):
                return True
        
        return False
    
    def _calculate_threat_level(self, black_boat: BlackBoat) -> int:
        """计算威胁等级 (1-3星)"""
        distance_to_breakthrough = self._calculate_distance_to_breakthrough(black_boat)
        
        # 距离因子 (0-1)
        max_distance = 300000  # 最大可能距离
        distance_factor = 1.0 - (distance_to_breakthrough / max_distance)
        
        # 速度因子 (0-1)
        speed_factor = black_boat.speed / GameConfig.BLACK_BOAT_MAX_SPEED
        
        # 航向因子 (0-1) - 朝向突破线的程度
        dx = 40000 - black_boat.x  # 突破线X坐标
        dy = 0  # 假设朝Y=black_boat.y方向
        target_heading = math.atan2(dy, dx)
        heading_diff = abs(target_heading - black_boat.heading)
        heading_factor = 1.0 - min(heading_diff, math.pi) / math.pi
        
        # 综合威胁分数
        threat_score = (distance_factor * 0.5 + speed_factor * 0.3 + heading_factor * 0.2)
        
        if threat_score > 0.7:
            return 3  # 高威胁
        elif threat_score > 0.4:
            return 2  # 中威胁
        else:
            return 1  # 低威胁
    
    def _calculate_distance_to_breakthrough(self, black_boat: BlackBoat) -> float:
        """计算到突破线的距离"""
        breakthrough_x = 40000  # 突破线X坐标
        return abs(breakthrough_x - black_boat.x)
    
    def _calculate_eta_to_breakthrough(self, black_boat: BlackBoat) -> float:
        """计算到达突破线的预计时间(分钟)"""
        distance = self._calculate_distance_to_breakthrough(black_boat)
        if black_boat.speed > 0:
            eta_seconds = distance / black_boat.speed
            return eta_seconds / 60.0
        return float('inf')
    
    def _get_detected_by(self, black_boat: BlackBoat, white_boats: List[WhiteBoat], 
                        white_drones: List[WhiteDrone]) -> str:
        """获取探测到该目标的单位"""
        detected_by = []
        
        # 检查无人船
        for white_boat in white_boats:
            if not white_boat.active:
                continue
            distance = white_boat.distance_to(black_boat)
            if distance <= GameConfig.WHITE_BOAT_DETECT_RANGE:
                detected_by.append(f"W{white_boat.id}")
        
        # 检查无人机
        for drone in white_drones:
            if drone.state != "flying":
                continue
            if drone.is_target_in_detection_sector(black_boat, drone.heading):
                detected_by.append(f"D{drone.id}")
        
        return ",".join(detected_by) if detected_by else "未知"
    
    def _predict_position(self, last_known: Dict, lost_time: float) -> Tuple[float, float]:
        """预测失联目标位置"""
        last_x, last_y = last_known['position']
        heading = last_known['heading']
        speed = last_known['speed']
        
        # 假设目标继续按最后已知的航向和速度前进
        predicted_x = last_x + speed * lost_time * math.cos(heading)
        predicted_y = last_y + speed * lost_time * math.sin(heading)
        
        return predicted_x, predicted_y


class GameVisualizer:
    """游戏可视化器"""
    
    def __init__(self, screen: pygame.Surface):
        """
        初始化可视化器
        
        Args:
            screen (pygame.Surface): 用于绘制的游戏窗口Surface对象
        """
        self.screen = screen
        self.window_width = self.screen.get_width()
        self.window_height = self.screen.get_height()
        
        # 信息面板配置
        self.info_panel_width = 400  # 增加左侧面板宽度
        self.right_map_width = 300  # 右侧白方已知地图宽度
        self.game_area_x = self.info_panel_width  # 游戏区域紧跟左侧面板
        self.game_area_width = self.window_width - self.info_panel_width - self.right_map_width - 50  # 减少右侧空隙
        
        # 游戏区域的真实坐标范围 (根据utils.py中的实际地图尺寸)
        # 从A7A8线段到A1A6线段大约是300km，加上边界缓冲
        self.game_min_x = -10000  # 左边界向左10km缓冲
        self.game_max_x = 310000  # 右边界向右10km缓冲 (实际地图约300km宽)
        self.game_min_y = -10000  # 下边界向下10km缓冲
        self.game_max_y = 683205  # 上边界向上10km缓冲 (实际地图约673km高)
        
        # 计算实际的世界坐标尺寸和比例
        self.world_width = self.game_max_x - self.game_min_x   # 320000
        self.world_height = self.game_max_y - self.game_min_y  # 693205
        self.world_aspect_ratio = self.world_width / self.world_height  # 约0.46
        
        # 计算屏幕游戏区域的比例
        self.screen_aspect_ratio = self.game_area_width / self.window_height
        
        # 根据比例调整显示区域，保持真实比例
        if self.world_aspect_ratio > self.screen_aspect_ratio:
            # 世界比屏幕更宽，以宽度为准
            self.display_scale = self.game_area_width / self.world_width
            self.display_width = self.game_area_width
            self.display_height = self.world_height * self.display_scale
            self.display_offset_x = 0
            self.display_offset_y = (self.window_height - self.display_height) / 2
        else:
            # 世界比屏幕更高，以高度为准
            self.display_scale = self.window_height / self.world_height
            self.display_width = self.world_width * self.display_scale
            self.display_height = self.window_height
            self.display_offset_x = (self.game_area_width - self.display_width) / 2
            self.display_offset_y = 0
        
        # 字体设置
        self.font_small = get_chinese_font(14)
        self.font_medium = get_chinese_font(18)
        self.font_large = get_chinese_font(24)
        
        # 颜色定义
        self.colors = {
            'background': (30, 30, 40),      # 深灰背景
            'water': (50, 100, 150),         # 海水蓝
            'boundary': (255, 255, 255),     # 白色边界
            'breakthrough_line': (255, 0, 0), # 红色突破线
            'deployment_line': (0, 255, 0),  # 绿色部署线
            'white_boat': (100, 150, 255),   # 蓝色白方无人艇
            'white_drone': (150, 200, 255),  # 淡蓝色无人机
            'black_boat': (255, 100, 100),   # 红色黑方无人艇
            'detect_range': (255, 255, 0, 50), # 半透明黄色探测范围
            'lock_range': (255, 0, 0, 30),   # 半透明红色锁定范围
            'text': (255, 255, 255),         # 白色文字
            'text_warning': (255, 255, 0),   # 黄色警告文字
            'text_danger': (255, 100, 100),  # 红色危险文字
        }
        
        # 时钟控制
        self.clock = pygame.time.Clock()
        
        # 状态信息
        self.show_ranges = True
        self.show_info_panel = True
        
        # 速度控制
        self.speed_multiplier = 1.0  # 速度倍数
        self.available_speeds = [1.0, 5.0, 10.0, 15.0]  # 可选速度
        self.speed_index = 0  # 当前速度索引
        
        # 信息面板
        self.info_panel_data = InfoPanelData()
        self.last_info_update = 0.0
        self.info_update_interval = 1.0  # 每秒更新一次
        self.selected_target = None  # 点击选中的目标
        self.camera_follow_target = None  # 相机跟随目标
        
        # 缓存信息面板数据
        self.cached_boat_info = []
        self.cached_drone_info = []
        self.cached_threats = []
        self.cached_predictions = []
        
        # 状态机信息
        self.fsm_info = None
        
    def world_to_screen(self, x: float, y: float) :
        """将世界坐标转换为屏幕坐标，保持真实比例"""
        # 将世界坐标标准化到0-1范围
        norm_x = (x - self.game_min_x) / self.world_width
        norm_y = (y - self.game_min_y) / self.world_height
        
        # 转换到屏幕坐标，保持比例并居中显示
        screen_x = int(self.game_area_x + self.display_offset_x + norm_x * self.display_width)
        screen_y = int(self.window_height - self.display_offset_y - norm_y * self.display_height)
        
        return screen_x, screen_y
    
    def world_to_right_map(self, x: float, y: float) -> Tuple[int, int]:
        """将世界坐标转换为右侧地图坐标"""
        # 右侧地图区域
        right_map_x = self.window_width - self.right_map_width
        
        # 将世界坐标标准化到0-1范围
        norm_x = (x - self.game_min_x) / self.world_width
        norm_y = (y - self.game_min_y) / self.world_height
        
        # 转换到右侧地图坐标，使用相同的比例但不同的区域
        map_width = self.right_map_width - 20  # 留出边距
        map_height = self.window_height - 40   # 留出边距
        
        screen_x = int(right_map_x + 10 + norm_x * map_width)
        screen_y = int(self.window_height - 20 - norm_y * map_height)
        
        return screen_x, screen_y
    
    def world_distance_to_screen(self, distance: float) -> int:
        """将世界距离转换为屏幕距离，保持真实比例"""
        screen_distance = int(distance * self.display_scale)
        return max(1, screen_distance)  # 至少1像素
    
    def render_frame(self, white_boats: List[WhiteBoat], white_drones: List[WhiteDrone], 
                    black_boats: List[BlackBoat], current_time: float, game_info: Optional[dict] = None):
        """
        渲染一帧画面
        
        Args:
            white_boats: 白方无人艇列表
            white_drones: 白方无人机列表
            black_boats: 黑方无人艇列表
            current_time: 当前时间
            game_info: 游戏信息字典
        """
        # 清空屏幕
        self.screen.fill(self.colors['background'])
        
        # 存储FSM信息
        self.fsm_info = game_info.get('fsm_info') if game_info else None
        
        # 更新信息面板数据（每秒更新一次）
        if current_time - self.last_info_update >= self.info_update_interval:
            self._update_info_panel_data(white_boats, white_drones, black_boats, current_time)
            self.last_info_update = current_time
        
        # 绘制左侧信息面板
        self._draw_left_info_panel(current_time)
        
        # 绘制游戏区域
        self._draw_game_area()
        
        # 绘制探测和锁定范围（在单位下方）
        if self.show_ranges:
            self._draw_detection_ranges(white_boats, white_drones, black_boats, current_time)
        
        # 绘制单位
        self._draw_units(white_boats, white_drones, black_boats, current_time)
        
       
        
        
        # 绘制右侧白方已知地图
        self._draw_white_known_map(white_boats, white_drones, black_boats, current_time)
        
        # 绘制控制说明
        self._draw_controls()
        
        # 更新显示 - 注意：simple_game_demo.py的循环会处理flip
        # pygame.display.flip()
    
    def _update_info_panel_data(self, white_boats: List[WhiteBoat], white_drones: List[WhiteDrone], 
                               black_boats: List[BlackBoat], current_time: float):
        """更新信息面板数据"""
        self.cached_boat_info = self.info_panel_data.collect_white_boat_info(white_boats, current_time)
        self.cached_drone_info = self.info_panel_data.collect_drone_info(white_drones)
        self.cached_threats, self.cached_predictions = self.info_panel_data.analyze_threats(
            black_boats, white_boats, white_drones, current_time)
    
    def _draw_left_info_panel(self, current_time: float):
        """绘制左侧信息面板"""
        # 清空之前的可点击区域
        self.clickable_areas = []
        
        # 绘制信息面板背景
        panel_surface = pygame.Surface((self.info_panel_width, self.window_height))
        panel_surface.set_alpha(240)
        panel_surface.fill((20, 25, 35))  # 深色背景
        self.screen.blit(panel_surface, (0, 0))
        
        # 绘制边界线
        pygame.draw.line(self.screen, (100, 100, 100), 
                        (self.info_panel_width-1, 0), (self.info_panel_width-1, self.window_height), 2)
        
        y_offset = 10
        
        # 主标题
        title_bg = pygame.Surface((self.info_panel_width - 20, 35))
        title_bg.set_alpha(120)
        title_bg.fill((80, 120, 160))
        self.screen.blit(title_bg, (10, y_offset))
        
        title_surface = self.font_medium.render(" 态势信息", True, (255, 255, 255))
        self.screen.blit(title_surface, (15, y_offset + 3))
        y_offset += 40
        
        # 绘制状态机信息（如果可用）
        # if hasattr(self, 'fsm_info') and self.fsm_info:
        #     y_offset = self._draw_fsm_section(y_offset)
        
        # 绘制白方单位状态
        y_offset = self._draw_white_units_section(y_offset)
        
        # 绘制简化的黑方目标信息（去除威胁等级）
        # y_offset = self._draw_simple_targets_section(y_offset)
        
        # 绘制游戏状态信息（整合原信息面板内容）
        y_offset = self._draw_game_status_section(y_offset, current_time)
    
    def _draw_white_units_section(self, y_start: int) -> int:
        """绘制白方单位状态区域"""
        y = y_start
        
        # 绘制区域背景
        section_height = max(50, min(200, self.window_height - y - 300))  # 预估区域高度，保证最小50像素
        # section_bg = pygame.Surface((self.info_panel_width - 20, section_height))
        # section_bg.set_alpha(60)
        # section_bg.fill((40, 60, 90))  # 蓝色调背景
        #self.screen.blit(section_bg, (10, y))
        
        # 区域标题
        section_title = self.font_small.render(" 白方单位状态", True, (120, 180, 255))
        self.screen.blit(section_title, (15, y + 5))
        y += 20
        
        # 绘制无人船信息
        for boat_info in self.cached_boat_info:
            y = self._draw_boat_info_item(boat_info, y)
            if y > self.window_height - 300:  # 为下方内容留出更多空间
                break
        
        # 绘制无人机信息
        if self.cached_drone_info:
            y += 10
            drone_title = self.font_small.render("无人机状态", True, (150, 200, 255))
            self.screen.blit(drone_title, (15, y))
            y += 25
            
            for drone_info in self.cached_drone_info:
                y = self._draw_drone_info_item(drone_info, y)
                # if y > self.window_height - 250:  
                # 调整限制，为下方section留出空间
                #     break
        
        return y + 15
    
    def _draw_threats_section(self, y_start: int) -> int:
        """绘制威胁目标区域"""
        y = y_start
        
        if not self.cached_threats:
            return y
        
        # 区域标题
        threat_count = len(self.cached_threats)
        section_title = self.font_small.render(f" 威胁目标 [{threat_count}个]", True, (255, 150, 100))
        self.screen.blit(section_title, (10, y))
        y += 25
        
        # 绘制威胁目标
        for threat_info in self.cached_threats[:20]:  # 最多显示6个
            y = self._draw_threat_info_item(threat_info, y)
            if y > self.window_height - 100:
                break
        
        return y + 10
    
    def _draw_predictions_section(self, y_start: int) -> int:
        """绘制预测目标区域"""
        y = y_start
        
        if not self.cached_predictions:
            return y
        
        # 区域标题
        pred_count = len(self.cached_predictions)
        section_title = self.font_small.render(f" 预测目标 [{pred_count}个]", True, (255, 255, 100))
        self.screen.blit(section_title, (10, y))
        y += 25
        
        # 绘制预测目标
        for pred_info in self.cached_predictions[:20]:  # 最多显示4个
            y = self._draw_prediction_info_item(pred_info, y)
            if y > self.window_height - 50:
                break
        
        return y + 10
    
    def _draw_fsm_section(self, y_start: int) -> int:
        """绘制状态机信息区域"""
        y = y_start
        
        if not self.fsm_info:
            return y
        
        # 区域标题
        section_title = self.font_small.render("🤖 状态机状态", True, (150, 200, 255))
        self.screen.blit(section_title, (10, y))
        y += 25
        
        # # 全局状态
        # global_state = self.fsm_info.get('global_state', 'UNKNOWN')
        # state_timer = self.fsm_info.get('state_timer', 0)
        # global_text = f"全局状态: {global_state} ({state_timer:.1f}s)"
        # global_surface = self.font_small.render(global_text, True, (255, 255, 100))
        # self.screen.blit(global_surface, (15, y))
        # y += 16
        
        # # 任务分配状态
        # task_ready = self.fsm_info.get('task_assignment_ready', False)
        # task_text = f"任务分配: {'就绪' if task_ready else '未就绪'}"
        # task_color = (100, 255, 100) if task_ready else (255, 150, 150)
        # task_surface = self.font_small.render(task_text, True, task_color)
        # self.screen.blit(task_surface, (15, y))
        # y += 16
        
        # 船只状态统计
        boat_states = self.fsm_info.get('boat_states', {})
        if boat_states:
            boat_text = f"船只状态数: {len(boat_states)}"
            boat_surface = self.font_small.render(boat_text, True, (200, 200, 200))
            self.screen.blit(boat_surface, (15, y))
            y += 16
            
            # 显示前几个船只的状态
            for i, (boat_id, state) in enumerate(list(boat_states.items())[:3]):
                state_text = f"  W{boat_id}: {state}"
                state_surface = self.font_small.render(state_text, True, (180, 180, 180))
                self.screen.blit(state_surface, (15, y))
                y += 14
        
        # 无人机状态统计
        drone_states = self.fsm_info.get('drone_states', {})
        if drone_states:
            drone_text = f"无人机状态数: {len(drone_states)}"
            drone_surface = self.font_small.render(drone_text, True, (200, 200, 200))
            self.screen.blit(drone_surface, (15, y))
            y += 16
        
        return y + 10
    
    def _draw_simple_targets_section(self, y_start: int) -> int:
        """绘制简化的黑方目标信息（去除威胁等级）"""
        y = y_start
        
        if not self.cached_threats:
            return y
        
        # 绘制区域背景
        section_height = max(50, min(150, self.window_height - y - 200))  # 保证最小50像素
        section_bg = pygame.Surface((self.info_panel_width - 20, section_height))
        section_bg.set_alpha(60)
        section_bg.fill((90, 60, 40))  # 橙色调背景
        self.screen.blit(section_bg, (10, y))
        
        # 区域标题
        target_count = len(self.cached_threats)
        section_title = self.font_small.render(f"探测目标 [{target_count}个]", True, (255, 180, 120))
        self.screen.blit(section_title, (15, y + 5))
        y += 30
        
        # 绘制目标信息（简化版）
        for threat_info in self.cached_threats[:10]:  # 最多显示10个
            y = self._draw_simple_target_item(threat_info, y)
            if y > self.window_height - 150:  # 为游戏状态section留出空间
                break
        
        return y + 15
    
    def _draw_simple_target_item(self, target_info: Dict, y: int) -> int:
        """绘制单个简化目标信息项（去除威胁等级）"""
        target_id = target_info['id']
        position = target_info['position']
        distance = target_info['distance_to_breakthrough'] / 1000  # 转换为km
        speed = target_info.get('speed', 0)
        
        # 主信息行
        main_text = f"B{target_id} 距突破{distance:.1f}km 速度{speed:.1f}m/s"
        text_surface = self.font_small.render(main_text, True, (255, 200, 150))
        text_rect = pygame.Rect(15, y, self.info_panel_width - 20, 16)
        self.screen.blit(text_surface, (15, y))
        
        # 保存点击区域
        self._add_clickable_area("target", target_id, text_rect, position)
        
        y += 16
        
        # 位置信息
        pos_text = f"  位置: ({position[0]},{position[1]})"
        pos_surface = self.font_small.render(pos_text, True, (200, 200, 200))
        self.screen.blit(pos_surface, (15, y))
        y += 14
        
        # 探测信息
        detected_text = f"  探测: {target_info['detected_by']}"
        detected_surface = self.font_small.render(detected_text, True, (150, 150, 150))
        self.screen.blit(detected_surface, (15, y))
        y += 14
        
        return y + 3
    
    def _draw_game_status_section(self, y_start: int, current_time: float) -> int:
        """绘制游戏状态信息区域（整合原信息面板内容）"""
        y = y_start
        
        # 绘制区域背景
        section_height = 100  # 保证最小50像素
        section_bg = pygame.Surface((self.info_panel_width - 20, section_height))
        section_bg.set_alpha(60)
        section_bg.fill((60, 80, 40))  # 绿色调背景
        self.screen.blit(section_bg, (10, y))
        
        # 区域标题
        section_title = self.font_small.render(" 游戏状态", True, (200, 255, 150))
        self.screen.blit(section_title, (15, y + 5))
        y += 30
        
        # 时间信息
        time_text = f"时间: {int(current_time)}秒 ({int(current_time//60)}分{int(current_time%60):02d}秒)"
        text_surface = self.font_small.render(time_text, True, (255, 255, 255))
        self.screen.blit(text_surface, (15, y))
        y += 16
        
        # 速度信息
        speed_text = f"速度: {self.speed_multiplier}x"
        speed_color = self.colors['text_warning'] if self.speed_multiplier > 1.0 else self.colors['text']
        text_surface = self.font_small.render(speed_text, True, speed_color)
        self.screen.blit(text_surface, (15, y))
        y += 16
        
        # 白方状态统计
        if hasattr(self, 'cached_boat_info') and hasattr(self, 'cached_drone_info'):
            active_white_boats = len([b for b in self.cached_boat_info if b.get('status') != '冻结'])
            flying_drones = len([d for d in self.cached_drone_info if d.get('state') == 'flying'])
            white_text = f"白方: {active_white_boats}艘活跃, {flying_drones}架飞行"
            text_surface = self.font_small.render(white_text, True, self.colors['white_boat'])
            self.screen.blit(text_surface, (15, y))
            y += 16
        
        # 黑方状态统计
        if hasattr(self, 'cached_threats'):
            detected_targets = len(self.cached_threats)
            black_text = f"黑方: {detected_targets}个探测目标"
            text_surface = self.font_small.render(black_text, True, self.colors['black_boat'])
            self.screen.blit(text_surface, (15, y))
            y += 16
        
        return y + 10
    
    def _draw_white_known_map(self, white_boats: List[WhiteBoat], white_drones: List[WhiteDrone], 
                             black_boats: List[BlackBoat], current_time: float):
        """绘制右侧白方已知地图"""
        # 右侧地图区域位置
        right_map_x = self.window_width - self.right_map_width
        
        # 绘制右侧地图背景
        map_surface = pygame.Surface((self.right_map_width, self.window_height))
        map_surface.set_alpha(200)
        map_surface.fill((15, 20, 30))  # 深色背景
        self.screen.blit(map_surface, (right_map_x, 0))
        
        # 绘制边界线
        pygame.draw.line(self.screen, (100, 100, 100), 
                        (right_map_x, 0), (right_map_x, self.window_height), 2)
        
        # 绘制标题
        title_bg = pygame.Surface((self.right_map_width - 20, 25))
        title_bg.set_alpha(120)
        title_bg.fill((80, 120, 160))
        self.screen.blit(title_bg, (right_map_x + 10, 10))
        
        title_surface = self.font_medium.render(" 白方已知地图", True, (255, 255, 255))
        self.screen.blit(title_surface, (right_map_x + 15, 13))
        
        # 绘制八边形边界（简化版）
        map_points = [self.world_to_right_map(x, y) for x, y in POLYGON_POINTS]
        pygame.draw.polygon(self.screen, self.colors['boundary'], map_points, 1)
        
        # 绘制突破线和部署线
        breakthrough_start = self.world_to_right_map(BREAKTHROUGH_LINE_START[0], BREAKTHROUGH_LINE_START[1])
        breakthrough_end = self.world_to_right_map(BREAKTHROUGH_LINE_END[0], BREAKTHROUGH_LINE_END[1])
        pygame.draw.line(self.screen, self.colors['breakthrough_line'], breakthrough_start, breakthrough_end, 2)
        
        deploy_start = self.world_to_right_map(DEPLOYMENT_LINE_START[0], DEPLOYMENT_LINE_START[1])
        deploy_end = self.world_to_right_map(DEPLOYMENT_LINE_END[0], DEPLOYMENT_LINE_END[1])
        pygame.draw.line(self.screen, self.colors['deployment_line'], deploy_start, deploy_end, 2)
        
        # 绘制白方单位（所有状态）
        for boat in white_boats:
            if not boat.active:
                continue
            
            center = self.world_to_right_map(boat.x, boat.y)
            color = self.colors['white_boat']
            
            if boat.is_frozen(current_time):
                color = (color[0] // 2, color[1] // 2, color[2])
            
            # 绘制小圆圈
            pygame.draw.circle(self.screen, color, center, 3)
            pygame.draw.circle(self.screen, (255, 255, 255), center, 3, 1)
            
            # 绘制ID
            text_surface = self.font_small.render(f"W{boat.id}", True, self.colors['text'])
            self.screen.blit(text_surface, (center[0] + 5, center[1] - 5))
        
        # 绘制无人机
        for drone in white_drones:
            center = self.world_to_right_map(drone.x, drone.y)
            color = self.colors['white_drone']
            
            if drone.state == "flying":
                # 小三角形
                size = 2
                points = [
                    (center[0] + size, center[1]),
                    (center[0] - size, center[1] - size),
                    (center[0] - size, center[1] + size)
                ]
                pygame.draw.polygon(self.screen, color, points)
                pygame.draw.polygon(self.screen, (255, 255, 255), points, 1)
            else:
                # 小圆圈
                pygame.draw.circle(self.screen, color, center, 2)
                pygame.draw.circle(self.screen, (255, 255, 255), center, 2, 1)
            
            # 绘制ID
            text_surface = self.font_small.render(f"D{drone.id}", True, self.colors['text'])
            self.screen.blit(text_surface, (center[0] + 5, center[1] - 5))
        
        # 基于FSM提供的每帧预测位置绘制黑方目标
        predicted_targets = {}
        if hasattr(self, 'fsm_info') and self.fsm_info:
            predicted_targets = self.fsm_info.get('predicted_black_targets', {}) or {}

        # 先用本帧活跃黑方ID过滤FSM提供的预测，避免显示已击沉目标
        if isinstance(predicted_targets, dict) and predicted_targets:
            active_int_ids = {b.id for b in black_boats if b.active}
            active_str_ids = {str(b.id) for b in black_boats if b.active}
            filtered = {}
            for uid, pos in predicted_targets.items():
                try:
                    uid_int = int(uid)
                except Exception:
                    uid_int = None
                if (uid_int is not None and uid_int in active_int_ids) or (uid in active_int_ids) or (str(uid) in active_str_ids):
                    filtered[uid] = pos
            predicted_targets = filtered

        # 若过滤后仍为空，则退回使用“当前帧确实被白方探测到”的黑方真实坐标
        if not predicted_targets:
            detected_ids = set()
            for boat in white_boats:
                if not boat.active:
                    continue
                for t in getattr(boat, 'detected_targets', []) or []:
                    if getattr(t, 'active', False):
                        detected_ids.add(getattr(t, 'id', None))
            for drone in white_drones:
                if getattr(drone, 'state', None) != 'flying':
                    continue
                for t in getattr(drone, 'detected_targets', []) or []:
                    if getattr(t, 'active', False):
                        detected_ids.add(getattr(t, 'id', None))
            fallback = {}
            for b in black_boats:
                if b.active and b.id in detected_ids:
                    fallback[b.id] = (float(b.x), float(b.y))
            predicted_targets = fallback

        for unit_id, pos in predicted_targets.items():
            try:
                px, py = float(pos[0]), float(pos[1])
            except Exception:
                continue
            center = self.world_to_right_map(px, py)
            color = (255, 255, 100)  # 黄色表示“已知目标”统一样式

            # 绘制小菱形
            size = 3
            points = [
                (center[0], center[1] - size),
                (center[0] + size, center[1]),
                (center[0], center[1] + size),
                (center[0] - size, center[1])
            ]
            pygame.draw.polygon(self.screen, color, points)
            pygame.draw.polygon(self.screen, (255, 255, 255), points, 1)

            # 绘制ID（直接使用unit_id的字符串形式）
            text_surface = self.font_small.render(f"B{unit_id}", True, (255, 255, 0))
            self.screen.blit(text_surface, (center[0] + 5, center[1] - 5))
        
        # 添加图例和统计信息
        self._draw_right_map_legend(right_map_x, white_boats, white_drones, black_boats)

    def _draw_right_map_legend(self, map_x: int, white_boats: List[WhiteBoat], 
                              white_drones: List[WhiteDrone], black_boats: List[BlackBoat]):
        """绘制右侧地图的图例和统计信息"""
        legend_y = self.window_height - 200  # 图例起始位置
        
        # 图例背景
        legend_bg = pygame.Surface((self.right_map_width - 20, 180))
        legend_bg.set_alpha(180)
        legend_bg.fill((25, 30, 40))
        self.screen.blit(legend_bg, (map_x + 10, legend_y))
        
        # 图例标题
        legend_title = self.font_small.render("图例", True, (255, 255, 255))
        self.screen.blit(legend_title, (map_x + 15, legend_y + 5))
        
        y = legend_y + 25
        
        # 白方船只图例
        pygame.draw.circle(self.screen, self.colors['white_boat'], (map_x + 20, y + 5), 3)
        pygame.draw.circle(self.screen, (255, 255, 255), (map_x + 20, y + 5), 3, 1)
        legend_text = self.font_small.render("白方船只", True, (200, 200, 200))
        self.screen.blit(legend_text, (map_x + 30, y))
        y += 18
        
        # 白方无人机图例
        drone_points = [(map_x + 22, y + 5), (map_x + 18, y + 2), (map_x + 18, y + 8)]
        pygame.draw.polygon(self.screen, self.colors['white_drone'], drone_points)
        legend_text = self.font_small.render("白方无人机", True, (200, 200, 200))
        self.screen.blit(legend_text, (map_x + 30, y))
        y += 18
        
        # 已知黑方目标图例（基于FSM预测位置）
        black_points = [(map_x + 20, y + 2), (map_x + 23, y + 5), (map_x + 20, y + 8), (map_x + 17, y + 5)]
        pygame.draw.polygon(self.screen, (255, 255, 100), black_points)
        legend_text = self.font_small.render("已知目标", True, (200, 200, 200))
        self.screen.blit(legend_text, (map_x + 30, y))
        y += 25
        
        # 统计信息
        stats_title = self.font_small.render("统计信息", True, (255, 255, 255))
        self.screen.blit(stats_title, (map_x + 15, y))
        y += 20
        
        # 活跃单位统计
        active_boats = len([b for b in white_boats if b.active])
        flying_drones = len([d for d in white_drones if d.state == "flying"])
        # 统计“已知目标”数量：优先FSM提供；对其按当前活跃黑方过滤；为空则沿用回退规则
        detected_count = 0
        predicted_dict = {}
        if hasattr(self, 'fsm_info') and self.fsm_info:
            predicted_dict = self.fsm_info.get('predicted_black_targets', {}) or {}
        if isinstance(predicted_dict, dict) and predicted_dict:
            active_int_ids = {b.id for b in black_boats if b.active}
            active_str_ids = {str(b.id) for b in black_boats if b.active}
            filtered_keys = []
            for uid in predicted_dict.keys():
                try:
                    uid_int = int(uid)
                except Exception:
                    uid_int = None
                if (uid_int is not None and uid_int in active_int_ids) or (uid in active_int_ids) or (str(uid) in active_str_ids):
                    filtered_keys.append(uid)
            detected_count = len(filtered_keys)
        else:
            detected_ids = set()
            for boat in white_boats:
                if not boat.active:
                    continue
                for t in getattr(boat, 'detected_targets', []) or []:
                    if getattr(t, 'active', False):
                        detected_ids.add(getattr(t, 'id', None))
            for drone in white_drones:
                if getattr(drone, 'state', None) != 'flying':
                    continue
                for t in getattr(drone, 'detected_targets', []) or []:
                    if getattr(t, 'active', False):
                        detected_ids.add(getattr(t, 'id', None))
            detected_count = sum(1 for b in black_boats if b.active and b.id in detected_ids)

        stats_text = [
            f"活跃船只: {active_boats}",
            f"飞行无人机: {flying_drones}",
            f"已知目标: {detected_count}"
        ]
        
        for stat in stats_text:
            stat_surface = self.font_small.render(stat, True, (180, 180, 180))
            self.screen.blit(stat_surface, (map_x + 15, y))
            y += 14

    
    def _draw_boat_info_item(self, boat_info: Dict, y: int) -> int:
        """绘制单个无人船信息项"""
        boat_id = boat_info['id']
        status = boat_info['status']
        position = boat_info['position']
        
        # 状态颜色
        status_colors = {
            "巡逻": (100, 255, 100),
            "拦截": (255, 200, 100),
            "锁定": (255, 100, 100),
            "冻结": (150, 150, 150)
        }
        status_color = status_colors.get(status, (255, 255, 255))
        
        # 获取状态机状态信息
        fsm_state = ""
        fsm_target = None
        if hasattr(self, 'fsm_info') and self.fsm_info:
            boat_states = self.fsm_info.get('boat_states', {})
            boat_targets = self.fsm_info.get('boat_targets', {})
            if boat_id in boat_states:
                fsm_state = boat_states[boat_id]
            if boat_id in boat_targets:
                fsm_target = boat_targets[boat_id]
        
        # 主信息行（加入状态机状态）
        if fsm_state:
            main_text = f"W{boat_id} {status} [{fsm_state}]"
        else:
            main_text = f"W{boat_id} {status}"
        text_surface = self.font_small.render(main_text, True, status_color)
        text_rect = pygame.Rect(15, y, self.info_panel_width - 20, 16)
        self.screen.blit(text_surface, (15, y))
        
        # 保存点击区域
        self._add_clickable_area("boat", boat_id, text_rect, position)
        
        y += 16
        
        # 位置信息
        pos_text = f"  位置: ({position[0]},{position[1]})"
        pos_surface = self.font_small.render(pos_text, True, (180, 180, 180))
        self.screen.blit(pos_surface, (15, y))
        y += 14
        
        # 速度和方向信息
        speed = boat_info.get('speed', 0)
        heading = boat_info.get('heading', 0)
        speed_and_heading_text= f"  速度: {speed:.1f}m/s,方向: {heading:.0f}°"
        
        speed_surface = self.font_small.render(speed_and_heading_text, True, (180, 180, 180))
        
        self.screen.blit(speed_surface, (15, y))
        y += 14

        
        
        # FSM目标信息（优先显示）
        if fsm_target:
            try:
                if isinstance(fsm_target, (list, tuple)) and len(fsm_target) >= 2:
                    target_text = f"  FSM目标: ({int(fsm_target[0])},{int(fsm_target[1])})"
                elif hasattr(fsm_target, '__len__') and len(fsm_target) >= 2:
                    # 处理numpy数组等
                    target_text = f"  FSM目标: ({int(fsm_target[0])},{int(fsm_target[1])})"
                else:
                    target_text = f"  FSM目标: {fsm_target}"
                target_surface = self.font_small.render(target_text, True, (150, 255, 150))
                self.screen.blit(target_surface, (15, y))
                y += 14
            except (TypeError, IndexError, ValueError):
                # 如果转换失败，显示原始信息
                target_text = f"  FSM目标: {str(fsm_target)}"
                target_surface = self.font_small.render(target_text, True, (150, 255, 150))
                self.screen.blit(target_surface, (15, y))
                y += 14
        
        # 原有目标信息（如果与FSM目标不同）
        elif boat_info['target']:
            target_text = f"  目标: ({boat_info['target'][0]},{boat_info['target'][1]})"
            target_surface = self.font_small.render(target_text, True, (200, 200, 200))
            self.screen.blit(target_surface, (15, y))
            y += 14
        
        # 锁定进度
        if boat_info['lock_progress'] > 0:
            progress = boat_info['lock_progress']
            progress_text = f"  锁定: {int(progress*100)}%"
            progress_surface = self.font_small.render(progress_text, True, (255, 255, 100))
            self.screen.blit(progress_surface, (15, y))
            
            # 进度条
            bar_x = 120
            bar_width = 80
            bar_height = 4
            pygame.draw.rect(self.screen, (100, 100, 100), (bar_x, y+6, bar_width, bar_height))
            pygame.draw.rect(self.screen, (255, 255, 100), (bar_x, y+6, int(bar_width * progress), bar_height))
            y += 16
        
        return y + 3
    
    def _draw_drone_info_item(self, drone_info: Dict, y: int) -> int:
        """绘制单个无人机信息项"""
        drone_id = drone_info['id']
        energy = drone_info['energy']
        mode = drone_info['mode']
        position = drone_info['position']
        state = drone_info['state']
        
        # 根据状态和能量设置颜色
        if state == "flying":
            energy_color = (255, 255, 100) if energy > 30 else (255, 100, 100)
        elif state == "recharging":
            energy_color = (100, 255, 255)  # 青色表示充电

        else:
            energy_color = (150, 150, 150)  # 灰色表示未知状态
        
        # 主信息行
        main_text = f"D{drone_id} {mode} {int(energy)}% ({position[0]},{position[1]})"
        text_surface = self.font_small.render(main_text, True, energy_color)
        text_rect = pygame.Rect(15, y, self.info_panel_width - 20, 16)
        self.screen.blit(text_surface, (15, y))
        
        # 保存点击区域
        self._add_clickable_area("drone", drone_id, text_rect, position)
        
        y += 16
        
        # 母船信息
        parent_text = f"  母船: W{drone_info['parent_boat']}"
        parent_surface = self.font_small.render(parent_text, True, (180, 180, 180))
        self.screen.blit(parent_surface, (15, y))
        y += 14
        
        # 速度和方向信息
        speed = drone_info.get('speed', 0)
        heading = drone_info.get('heading', 0)
        speed_and_heading_text = f"  速度: {speed:.1f}m/s"
        
        speed_surface = self.font_small.render(speed_and_heading_text, True, (180, 180, 180))
        
        self.screen.blit(speed_surface, (15, y))
        y += 14
        
        return y + 3
    
    def _draw_threat_info_item(self, threat_info: Dict, y: int) -> int:
        """绘制单个威胁目标信息项"""
        threat_id = threat_info['id']
        threat_level = threat_info['threat_level']
        position = threat_info['position']
        distance = threat_info['distance_to_breakthrough'] / 1000  # 转换为km
        eta = threat_info['eta_minutes']
        
        # 威胁等级显示
        stars = "★" * threat_level + "☆" * (3 - threat_level)
        
        # 威胁颜色
        threat_colors = {1: (255, 255, 100), 2: (255, 200, 100), 3: (255, 100, 100)}
        threat_color = threat_colors.get(threat_level, (255, 255, 255))
        
        # 主信息行
        main_text = f"B{threat_id} {stars} 距突破{distance:.1f}km"
        text_surface = self.font_small.render(main_text, True, threat_color)
        text_rect = pygame.Rect(15, y, self.info_panel_width - 20, 16)
        self.screen.blit(text_surface, (15, y))
        
        # 保存点击区域
        self._add_clickable_area("threat", threat_id, text_rect, position)
        
        y += 16
        
        # 详细信息
        if eta < 60:  # 小于60分钟才显示ETA
            eta_text = f"  ETA: {eta:.1f}分钟 ({position[0]},{position[1]})"
        else:
            eta_text = f"  位置: ({position[0]},{position[1]})"
        eta_surface = self.font_small.render(eta_text, True, (200, 200, 200))
        self.screen.blit(eta_surface, (15, y))
        y += 14
        
        # 探测信息
        detected_text = f"  探测: {threat_info['detected_by']}"
        detected_surface = self.font_small.render(detected_text, True, (150, 150, 150))
        self.screen.blit(detected_surface, (15, y))
        y += 14
        
        return y + 3
    
    def _draw_prediction_info_item(self, pred_info: Dict, y: int) -> int:
        """绘制单个预测目标信息项"""
        pred_id = pred_info['id']
        predicted_pos = pred_info['predicted_position']
        lost_time = pred_info['lost_time']
        confidence = pred_info['confidence']
        
        # 置信度颜色
        conf_color = (100, 255, 100) if confidence > 0.7 else (255, 200, 100) if confidence > 0.4 else (255, 100, 100)
        
        # 主信息行
        main_text = f"B{pred_id} 预测({predicted_pos[0]},{predicted_pos[1]})"
        text_surface = self.font_small.render(main_text, True, conf_color)
        text_rect = pygame.Rect(15, y, self.info_panel_width - 20, 16)
        self.screen.blit(text_surface, (15, y))
        
        # 保存点击区域
        self._add_clickable_area("prediction", pred_id, text_rect, predicted_pos)
        
        y += 16
        
        # 失联信息
        lost_text = f"  失联: {int(lost_time)}s 置信度: {int(confidence*100)}%"
        lost_surface = self.font_small.render(lost_text, True, (180, 180, 180))
        self.screen.blit(lost_surface, (15, y))
        y += 14
        
        return y + 3
    
    def _add_clickable_area(self, item_type: str, item_id: int, rect: pygame.Rect, position: Tuple[int, int]):
        """添加可点击区域信息"""
        if not hasattr(self, 'clickable_areas'):
            self.clickable_areas = []
        
        self.clickable_areas.append({
            'type': item_type,
            'id': item_id,
            'rect': rect,
            'position': position
        })
    
    def _draw_game_area(self):
        """绘制游戏区域"""
        # 绘制海水背景
        water_surface = pygame.Surface((self.window_width, self.window_height))
        water_surface.fill(self.colors['water'])
        water_surface.set_alpha(100)
        self.screen.blit(water_surface, (0, 0))
        
        # 绘制八边形边界
        screen_points = [self.world_to_screen(x, y) for x, y in POLYGON_POINTS]
        pygame.draw.polygon(self.screen, self.colors['boundary'], screen_points, 2)
        
        # 绘制突破线 A1A6 (红线)
        start_screen = self.world_to_screen(BREAKTHROUGH_LINE_START[0], BREAKTHROUGH_LINE_START[1])
        end_screen = self.world_to_screen(BREAKTHROUGH_LINE_END[0], BREAKTHROUGH_LINE_END[1])
        pygame.draw.line(self.screen, self.colors['breakthrough_line'], start_screen, end_screen, 3)
        
        # 绘制白方部署线 A7A8 (绿线)
        deploy_start = self.world_to_screen(DEPLOYMENT_LINE_START[0], DEPLOYMENT_LINE_START[1])
        deploy_end = self.world_to_screen(DEPLOYMENT_LINE_END[0], DEPLOYMENT_LINE_END[1])
        pygame.draw.line(self.screen, self.colors['deployment_line'], deploy_start, deploy_end, 3)
        
        # 添加线段标签
        # 突破线标签
        line_mid_x = (start_screen[0] + end_screen[0]) // 2
        line_mid_y = (start_screen[1] + end_screen[1]) // 2
        text_surface = self.font_small.render("突破线", True, self.colors['breakthrough_line'])
        self.screen.blit(text_surface, (line_mid_x - 20, line_mid_y))
        
        # 部署线标签
        deploy_mid_x = (deploy_start[0] + deploy_end[0]) // 2
        deploy_mid_y = (deploy_start[1] + deploy_end[1]) // 2
        text_surface = self.font_small.render("白方部署线", True, self.colors['deployment_line'])
        self.screen.blit(text_surface, (deploy_mid_x + 10, deploy_mid_y))
        
        # 显示比例信息（在游戏区域右下角）
        scale_info = f"比例: 1:{int(1/self.display_scale*1000)}km"
        world_size_info = f"地图: {int(self.world_width/1000)}km × {int(self.world_height/1000)}km"
        
        scale_x = self.game_area_x + self.game_area_width - 150
        scale_y = self.window_height - 60
        
        scale_surface = self.font_small.render(scale_info, True, (200, 200, 200))
        self.screen.blit(scale_surface, (scale_x, scale_y))
        
        size_surface = self.font_small.render(world_size_info, True, (200, 200, 200))
        self.screen.blit(size_surface, (scale_x, scale_y + 15))
    
    def _draw_detection_ranges(self, white_boats: List[WhiteBoat], white_drones: List[WhiteDrone], 
                             black_boats: List[BlackBoat], current_time: float):
        """绘制探测和锁定范围"""
        
        # 创建透明表面用于绘制范围
        range_surface = pygame.Surface((self.window_width, self.window_height))
        range_surface.set_alpha(50)
        
        # 白方无人艇探测范围
        for boat in white_boats:
            if not boat.active or boat.is_frozen(current_time):
                continue
            
            center = self.world_to_screen(boat.x, boat.y)
            
            # 探测范围 (黄色圆圈)
            detect_radius = self.world_distance_to_screen(GameConfig.WHITE_BOAT_DETECT_RANGE)
            if detect_radius > 2:
                pygame.draw.circle(range_surface, self.colors['detect_range'][:3], center, detect_radius, 1)
            
            # 锁定范围 (红色圆圈)
            lock_radius = self.world_distance_to_screen(GameConfig.WHITE_BOAT_LOCK_RANGE)
            if lock_radius > 2:
                pygame.draw.circle(range_surface, self.colors['lock_range'][:3], center, lock_radius, 1)
        
        # 白方无人机探测范围（扇形）
        for drone in white_drones:
            if drone.state != "flying":
                continue
            
            center = self.world_to_screen(drone.x, drone.y)
            detect_radius = self.world_distance_to_screen(GameConfig.WHITE_DRONE_DETECT_RANGE)
            
            if detect_radius > 5:
                # 绘制60度探测扇形
                self._draw_detection_sector(range_surface, center, detect_radius, 
                                          drone.heading, GameConfig.WHITE_DRONE_DETECT_ANGLE)
        
        # 黑方无人艇探测范围
        for boat in black_boats:
            if not boat.active or boat.is_frozen(current_time):
                continue
            
            center = self.world_to_screen(boat.x, boat.y)
            detect_radius = self.world_distance_to_screen(GameConfig.BLACK_BOAT_DETECT_RANGE)
            
            if detect_radius > 2:
                pygame.draw.circle(range_surface, (255, 150, 150), center, detect_radius, 1)
        
        self.screen.blit(range_surface, (0, 0))
    
    def _draw_detection_sector(self, surface: pygame.Surface, center: Tuple[int, int], 
                             radius: int, heading: float, angle_degrees: float):
        """绘制扇形探测范围"""
        if radius < 3:
            return
        
        angle_rad = math.radians(angle_degrees)
        half_angle = angle_rad / 2
        
        # 计算扇形的点
        points = [center]
        
        # 添加扇形边缘的点
        num_points = max(8, int(angle_degrees / 5))  # 根据角度调整点数
        for i in range(num_points + 1):
            current_angle = heading - half_angle + (angle_rad * i / num_points)
            x = center[0] + radius * math.cos(current_angle)
            y = center[1] - radius * math.sin(current_angle)  # 注意Y轴方向
            points.append((int(x), int(y)))
        
        # 绘制扇形
        if len(points) > 2:
            pygame.draw.polygon(surface, (255, 255, 0), points, 1)
    
    def _is_black_boat_detected(self, black_boat: BlackBoat, white_boats: List[WhiteBoat], 
                               white_drones: List[WhiteDrone]) -> bool:
        """检查黑方船只是否被白方单位探测到"""
        # 检查是否被白方无人船探测到
        for white_boat in white_boats:
            if not white_boat.active:
                continue
            # 直接检查是否在探测列表中
            if hasattr(white_boat, 'detected_targets') and black_boat in white_boat.detected_targets:
                return True
            # 如果没有探测列表，则手动计算距离
            distance = white_boat.distance_to(black_boat)
            if distance <= GameConfig.WHITE_BOAT_DETECT_RANGE:
                return True
        
        # 检查是否被白方无人机探测到
        for drone in white_drones:
            if drone.state != "flying":
                continue
            # 直接检查是否在探测列表中
            if hasattr(drone, 'detected_targets') and black_boat in drone.detected_targets:
                return True
            # 如果没有探测列表，则手动检查扇形范围
            if drone.is_target_in_detection_sector(black_boat, drone.heading):
                return True
        
        return False
    
    def _draw_units(self, white_boats: List[WhiteBoat], white_drones: List[WhiteDrone], 
                   black_boats: List[BlackBoat], current_time: float):
        """绘制所有单位"""
        
        # 绘制白方无人艇
        for boat in white_boats:
            if not boat.active:
                continue
            
            center = self.world_to_screen(boat.x, boat.y)
            color = self.colors['white_boat']
            
            # 根据状态调整颜色
            if boat.is_frozen(current_time):
                color = (color[0] // 2, color[1] // 2, color[2])  # 暗化表示冻结
            
            # 绘制船体 (圆形)
            pygame.draw.circle(self.screen, color, center, 8)
            pygame.draw.circle(self.screen, (255, 255, 255), center, 8, 2)
            
            # 绘制航向指示器
            heading_length = 15
            end_x = center[0] + heading_length * math.cos(boat.heading)
            end_y = center[1] - heading_length * math.sin(boat.heading)
            pygame.draw.line(self.screen, (255, 255, 255), center, (int(end_x), int(end_y)), 2)
            
            # 绘制ID
            text_surface = self.font_small.render(f"W{boat.id}", True, self.colors['text'])
            self.screen.blit(text_surface, (center[0] + 12, center[1] - 8))
            
            # 如果正在锁定，绘制锁定指示器
            if boat.is_locking and boat.current_target:
                target_center = self.world_to_screen(boat.current_target.x, boat.current_target.y)
                pygame.draw.line(self.screen, (255, 255, 0), center, target_center, 2)
                
                # 绘制锁定进度
                lock_duration = boat.get_lock_duration(current_time)
                progress = min(1.0, lock_duration / GameConfig.WHITE_BOAT_LOCK_DURATION)
                bar_width = 20
                bar_height = 4
                bar_x = center[0] - bar_width // 2
                bar_y = center[1] - 20
                
                pygame.draw.rect(self.screen, (100, 100, 100), (bar_x, bar_y, bar_width, bar_height))
                pygame.draw.rect(self.screen, (255, 255, 0), (bar_x, bar_y, int(bar_width * progress), bar_height))
        
        # 绘制白方无人机（所有状态）
        for drone in white_drones:
            center = self.world_to_screen(drone.x, drone.y)
            color = self.colors['white_drone']
            
            if drone.state == "flying":
                # 飞行中的无人机：正常大小的三角形
                size = 6
                nose_x = center[0] + size * math.cos(drone.heading)
                nose_y = center[1] - size * math.sin(drone.heading)
                left_wing_x = center[0] + size * math.cos(drone.heading + 2.4)
                left_wing_y = center[1] - size * math.sin(drone.heading + 2.4)
                right_wing_x = center[0] + size * math.cos(drone.heading - 2.4)
                right_wing_y = center[1] - size * math.sin(drone.heading - 2.4)
                points = [(int(nose_x), int(nose_y)), (int(left_wing_x), int(left_wing_y)), (int(right_wing_x), int(right_wing_y))]
                pygame.draw.polygon(self.screen, color, points)
                pygame.draw.polygon(self.screen, (255, 255, 255), points, 1)
                # 能量条
                energy_percentage = drone.energy / 100.0
                bar_width = 15
                bar_height = 3
                bar_x = center[0] - bar_width // 2
                bar_y = center[1] + 10
                pygame.draw.rect(self.screen, (100, 100, 100), (bar_x, bar_y, bar_width, bar_height))
                energy_color = (255, 255, 0) if energy_percentage > 0.3 else (255, 100, 100)
                pygame.draw.rect(self.screen, energy_color, (bar_x, bar_y, int(bar_width * energy_percentage), bar_height))
                # 状态指示
                status_y = center[1] + 15
                # 用mode属性区分
                mode = getattr(drone, 'mode', None)
                if mode == 1:
                    status_text = "跟踪"
                    status_color = (255, 100, 100)
                elif mode == 0:
                    status_text = "返回"
                    status_color = (100, 255, 100)
                elif mode is not None:
                    status_text = "巡逻"
                    status_color = (100, 100, 255)
                else:
                    status_text = None
                if status_text:
                    status_surface = self.font_small.render(status_text, True, status_color)
                    status_rect = status_surface.get_rect(center=(center[0], status_y))
                    self.screen.blit(status_surface, status_rect)
            elif drone.state == "recharging":
                # 充电中的无人机：黄色小圆圈
                radius = 4
                color = (255, 255, 100)
                pygame.draw.circle(self.screen, color, center, radius)
                pygame.draw.circle(self.screen, (255, 255, 255), center, radius, 1)
                # 能量条
                energy_percentage = drone.energy / 100.0
                bar_width = 12
                bar_height = 2
                bar_x = center[0] - bar_width // 2
                bar_y = center[1] + 8
                pygame.draw.rect(self.screen, (100, 100, 100), (bar_x, bar_y, bar_width, bar_height))
                energy_color = (100, 255, 100) if energy_percentage > 0.9 else (255, 255, 100) if energy_percentage > 0.3 else (255, 100, 100)
                pygame.draw.rect(self.screen, energy_color, (bar_x, bar_y, int(bar_width * energy_percentage), bar_height))
                # 状态文字
                status_text = "充电"
                status_surface = self.font_small.render(status_text, True, color)
                status_rect = status_surface.get_rect(center=(center[0], center[1] + 15))
                self.screen.blit(status_surface, status_rect)
            elif drone.state == "ready":
                # 就绪状态：灰色小圆圈
                radius = 4
                color = (180, 180, 180)
                pygame.draw.circle(self.screen, color, center, radius)
                pygame.draw.circle(self.screen, (255, 255, 255), center, radius, 1)
                # 能量条
                energy_percentage = drone.energy / 100.0
                bar_width = 12
                bar_height = 2
                bar_x = center[0] - bar_width // 2
                bar_y = center[1] + 8
                pygame.draw.rect(self.screen, (100, 100, 100), (bar_x, bar_y, bar_width, bar_height))
                energy_color = (100, 255, 100) if energy_percentage > 0.9 else (255, 255, 100) if energy_percentage > 0.3 else (255, 100, 100)
                pygame.draw.rect(self.screen, energy_color, (bar_x, bar_y, int(bar_width * energy_percentage), bar_height))
                # 状态文字
                status_text = "就绪"
                status_surface = self.font_small.render(status_text, True, color)
                status_rect = status_surface.get_rect(center=(center[0], center[1] + 15))
                self.screen.blit(status_surface, status_rect)
            else:
                # 其它未知状态：灰色小圆圈
                radius = 4
                color = (150, 150, 150)
                pygame.draw.circle(self.screen, color, center, radius)
                pygame.draw.circle(self.screen, (255, 255, 255), center, radius, 1)
                # 能量条
                energy_percentage = drone.energy / 100.0
                bar_width = 12
                bar_height = 2
                bar_x = center[0] - bar_width // 2
                bar_y = center[1] + 8
                pygame.draw.rect(self.screen, (100, 100, 100), (bar_x, bar_y, bar_width, bar_height))
                energy_color = (100, 255, 100) if energy_percentage > 0.9 else (255, 255, 100) if energy_percentage > 0.3 else (255, 100, 100)
                pygame.draw.rect(self.screen, energy_color, (bar_x, bar_y, int(bar_width * energy_percentage), bar_height))
                # 状态文字
                status_text = drone.state if hasattr(drone, 'state') else "未知"
                status_surface = self.font_small.render(status_text, True, color)
                status_rect = status_surface.get_rect(center=(center[0], center[1] + 15))
                self.screen.blit(status_surface, status_rect)

        # 绘制黑方无人艇
        for boat in black_boats:
            if not boat.active:
                continue
            
            center = self.world_to_screen(boat.x, boat.y)
            color = self.colors['black_boat']
            
            # 检查是否被探测到
            is_detected = self._is_black_boat_detected(boat, white_boats, white_drones)
            
            # 根据状态调整颜色
            if boat.is_frozen(current_time):
                color = (color[0] // 2, color[1] // 2, color[2] // 2)  # 暗化表示冻结
            elif is_detected:
                # 被探测到的船只使用亮黄色高亮
                color = (255, 255, 100)  # 亮黄色高亮
            
            # 绘制船体 (菱形)
            size = 8
            points = [
                (center[0], center[1] - size),  # 上
                (center[0] + size, center[1]),  # 右
                (center[0], center[1] + size),  # 下
                (center[0] - size, center[1])   # 左
            ]
            pygame.draw.polygon(self.screen, color, points)
            
            # 如果被探测到，绘制额外的高亮边框
            if is_detected and not boat.is_frozen(current_time):
                pygame.draw.polygon(self.screen, (255, 255, 0), points, 3)  # 黄色粗边框
                # 绘制探测指示器（闪烁的圆圈）
                highlight_radius = 12
                highlight_color = (255, 255, 0, 150)  # 半透明黄色
                pygame.draw.circle(self.screen, highlight_color[:3], center, highlight_radius, 2)
            else:
                pygame.draw.polygon(self.screen, (255, 255, 255), points, 2)  # 普通白色边框
            
            # 绘制航向指示器
            heading_length = 12
            end_x = center[0] + heading_length * math.cos(boat.heading)
            end_y = center[1] - heading_length * math.sin(boat.heading)
            pygame.draw.line(self.screen, (255, 255, 255), center, (int(end_x), int(end_y)), 2)
            
            # 绘制ID和锁定次数
            text_color = (255, 255, 0) if is_detected else self.colors['text']  # 被探测到时使用黄色文字
            text_surface = self.font_small.render(f"B{boat.id}", True, text_color)
            self.screen.blit(text_surface, (center[0] + 12, center[1] - 8))
            
            if boat.locked_times > 0:
                lock_text = f"锁定{boat.locked_times}"
                text_surface = self.font_small.render(lock_text, True, self.colors['text_danger'])
                self.screen.blit(text_surface, (center[0] + 12, center[1] + 8))
            
            # 如果被探测到，显示探测状态
            if is_detected and not boat.is_frozen(current_time):
                detected_text = "已探测"
                detected_surface = self.font_small.render(detected_text, True, (255, 255, 0))
                self.screen.blit(detected_surface, (center[0] + 12, center[1] + 20))
            
            # 如果正在锁定其他目标，绘制锁定线
            if boat.is_locking and boat.current_target:
                target_center = self.world_to_screen(boat.current_target.x, boat.current_target.y)
                pygame.draw.line(self.screen, (255, 100, 100), center, target_center, 2)
    
    def _draw_info_panel(self, white_boats: List[WhiteBoat], white_drones: List[WhiteDrone], 
                        black_boats: List[BlackBoat], current_time: float, game_info: dict):
        """绘制信息面板（移动到左下角）"""
        # 背景面板配置
        panel_width = 300
        panel_height = 200
        line_height = 22
        
        # 位置调整到左下角，但要避开左侧信息面板
        panel_x = self.info_panel_width + 10  # 在左侧信息面板右侧
        panel_y = self.window_height - panel_height - 10  # 底部
        
        panel_surface = pygame.Surface((panel_width, panel_height))
        panel_surface.set_alpha(180)
        panel_surface.fill((0, 0, 0))
        self.screen.blit(panel_surface, (panel_x, panel_y))
        
        # 时间信息
        time_text = f"时间: {int(current_time)}秒 ({int(current_time//60)}分{int(current_time%60):02d}秒)"
        text_surface = self.font_medium.render(time_text, True, self.colors['text'])
        self.screen.blit(text_surface, (panel_x + 10, panel_y + 10))
        
        # 速度信息
        speed_text = f"速度: {self.speed_multiplier}x"
        speed_color = self.colors['text_warning'] if self.speed_multiplier > 1.0 else self.colors['text']
        text_surface = self.font_small.render(speed_text, True, speed_color)
        self.screen.blit(text_surface, (panel_x + 220, panel_y + 12))
        
        y_offset = panel_y + 35
        
        # 白方状态
        active_white_boats = sum(1 for boat in white_boats if boat.active)
        flying_drones = sum(1 for drone in white_drones if drone.state == "flying")
        white_text = f"白方: {active_white_boats}艘无人艇, {flying_drones}架无人机在飞"
        text_surface = self.font_small.render(white_text, True, self.colors['white_boat'])
        self.screen.blit(text_surface, (panel_x + 10, y_offset))
        y_offset += line_height
        
        # 黑方状态
        active_black_boats = sum(1 for boat in black_boats if boat.active)
        crossed_boats = sum(1 for boat in black_boats if boat.crossed)
        black_text = f"黑方: {active_black_boats}艘活跃, {crossed_boats}艘突破"
        text_surface = self.font_small.render(black_text, True, self.colors['black_boat'])
        self.screen.blit(text_surface, (panel_x + 10, y_offset))
        y_offset += line_height
        
        # 锁定状态统计
        frozen_white = sum(1 for boat in white_boats if boat.active and boat.is_frozen(current_time))
        frozen_black = sum(1 for boat in black_boats if boat.active and boat.is_frozen(current_time))
        if frozen_white > 0 or frozen_black > 0:
            frozen_text = f"冻结: 白方{frozen_white}艘, 黑方{frozen_black}艘"
            text_surface = self.font_small.render(frozen_text, True, self.colors['text_warning'])
            self.screen.blit(text_surface, (panel_x + 10, y_offset))
            y_offset += line_height
        
        # 游戏信息
        if game_info:
            for key, value in game_info.items():
                info_text = f"{key}: {value}"
                text_surface = self.font_small.render(info_text, True, self.colors['text'])
                self.screen.blit(text_surface, (panel_x + 10, y_offset))
                y_offset += line_height
                if y_offset > panel_y + panel_height - 25:
                    break
    
    def _draw_controls(self):
        """绘制控制说明"""
        controls = [
            "空格: 切换速度 (1x/5x/10x/15x)",
            "ESC: 退出"
        ]
        
        # 绘制在游戏区域底部，避开右侧地图图例
        start_x = self.game_area_x + 10
        controls_height = len(controls) * 18 + 10
        y = self.window_height - controls_height - 10
        
        # 绘制半透明背景
        controls_bg = pygame.Surface((300, controls_height))
        controls_bg.set_alpha(120)
        controls_bg.fill((25, 30, 40))
        self.screen.blit(controls_bg, (start_x - 5, y - 5))
        
        for control in controls:
            text_surface = self.font_small.render(control, True, self.colors['text'])
            self.screen.blit(text_surface, (start_x, y))
            y += 18
    
    def handle_event(self, event: pygame.event.Event):
        """
        处理单个pygame事件
        
        Args:
            event (pygame.event.Event): Pygame事件对象
        
        Returns:
            bool: True表示继续运行，False表示退出
        """
        if event.type == pygame.QUIT:
            return False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                return False
            elif event.key == pygame.K_r:
                self.show_ranges = not self.show_ranges
            elif event.key == pygame.K_i:
                self.show_info_panel = not self.show_info_panel
            elif event.key == pygame.K_SPACE:
                # 空格键切换速度
                self._cycle_speed()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # 左键点击
                self._handle_mouse_click(event.pos)
        
        return True
    
    def _handle_mouse_click(self, mouse_pos: Tuple[int, int]):
        """处理鼠标点击事件"""
        mouse_x, mouse_y = mouse_pos
        
        # 检查是否点击了信息面板中的项目
        if hasattr(self, 'clickable_areas'):
            for area in self.clickable_areas:
                if area['rect'].collidepoint(mouse_x, mouse_y):
                    position = area['position']
                    print(f"点击定位到: {area['type']} {area['id']} at {position}")
                    
                    # 这里可以添加相机跟随功能
                    # 暂时只打印信息，后续可以实现视角跳转
                    return
    
    def _cycle_speed(self):
        """循环切换速度"""
        self.speed_index = (self.speed_index + 1) % len(self.available_speeds)
        self.speed_multiplier = self.available_speeds[self.speed_index]
        print(f"游戏速度: {self.speed_multiplier}x")
    
    def limit_fps(self, fps: int = 30):
        """限制帧率"""
        self.clock.tick(fps)
    
    def draw_game_over_overlay(self, result: str, game_stats: dict, current_time: float):
        """绘制游戏结束叠加层"""
        # 创建半透明黑色覆盖层
        overlay = pygame.Surface((self.window_width, self.window_height))
        overlay.fill((0, 0, 0))
        overlay.set_alpha(160)  # 半透明
        self.screen.blit(overlay, (0, 0))
        
        # 计算居中位置
        center_x = self.window_width // 2
        center_y = self.window_height // 2
        
        # 游戏结束标题
        title_text = "游戏结束"
        title_surface = self.font_large.render(title_text, True, (255, 255, 255))
        title_rect = title_surface.get_rect(center=(center_x, center_y - 150))
        self.screen.blit(title_surface, title_rect)
        
        # 游戏结果
        result_color = (100, 255, 100) if "白方" in result else (255, 100, 100)
        result_surface = self.font_medium.render(result, True, result_color)
        result_rect = result_surface.get_rect(center=(center_x, center_y - 100))
        self.screen.blit(result_surface, result_rect)
        
        # 统计信息（按需求的5项 + 可选附加信息）
        stats_y = center_y - 50
        crossed_black = game_stats.get('crossed_black_boats', 0)
        collision_count = game_stats.get('collision_count', 0)
        white_lock_count = game_stats.get('white_lock_count', 0)  # 白方锁定成功次数≈黑方被锁定次数
        black_lock_count = game_stats.get('black_lock_count', 0)  # 黑方锁定成功次数≈白方被锁定次数
        first_break_time = game_stats.get('first_breakthrough_time', None)
        # 阻击时间：从游戏开始到第一个黑方突破；无突破则显示固定100小时
        if first_break_time is None:
            intercept_time_text = "100小时"
        else:
            total_seconds = int(first_break_time)
            minutes = total_seconds // 60
            seconds = total_seconds % 60
            intercept_time_text = f"{minutes}分{seconds:02d}秒"

        # 核心5项
        stats_info = [
            f"黑方突防成功数量: {crossed_black}",
            f"白方阻击时间: {intercept_time_text}",
            f"白方被锁定次数: {black_lock_count}",
            f"黑方被锁定次数: {white_lock_count}",
            f"白方发生碰撞次数: {collision_count}",
        ]
        # 可选附加：游戏时长与步数
        stats_info.append(f"游戏时长: {int(current_time)}秒 ({int(current_time//60)}分{int(current_time%60):02d}秒)")
        if 'steps' in game_stats:
            stats_info.append(f"总步数: {game_stats.get('steps', 0)}")
        
        for i, stat in enumerate(stats_info):
            stat_surface = self.font_small.render(stat, True, (255, 255, 255))
            stat_rect = stat_surface.get_rect(center=(center_x, stats_y + i * 25))
            self.screen.blit(stat_surface, stat_rect)
        
        # 操作提示
        hint_y = center_y + 180
        hint_text = "按 回车键 或 ESC键 退出游戏"
        hint_surface = self.font_medium.render(hint_text, True, (255, 255, 0))
        hint_rect = hint_surface.get_rect(center=(center_x, hint_y))
        self.screen.blit(hint_surface, hint_rect)
        
        # 更新显示
        pygame.display.flip()
    
    def cleanup(self):
        """清理资源"""
        pygame.quit() 